package com.skyline.base.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.skyline.base.exception.NoOperatePermissionException;
import com.skyline.base.exception.NoResourceException;
import com.skyline.base.exception.NoVisitPermissionException;
import com.skyline.base.exception.NotLoginException;
import com.skyline.base.exception.OperateFailedException;
import com.skyline.common.exception.BusinessException;
import com.skyline.common.util.Constant;
import com.skyline.common.util.WebHelper;
import com.skyline.common.validation.Errors;
import com.skyline.common.validation.ValidationUtils;
import com.skyline.user.model.User;

//TODO:加注释
public class BaseController {
	private static final Log LOGGER = LogFactory.getLog(BaseController.class);
	protected static final String URL_SUFFIX = ".html";

	protected String buildRecirectPath(String baseUrl) {
		HttpServletRequest request = WebHelper.initRequest(null);
		return request.getContextPath() + baseUrl + URL_SUFFIX;
	}

	@ExceptionHandler(BusinessException.class)
	protected String handlerBusinsessException(HttpServletRequest request, BusinessException ex) {
		// FIXME 需要做处理
		if (ex instanceof NoVisitPermissionException) {
			LOGGER.warn("系统发生业务异常，异常原因：没有访问权限", ex);
		} else if (ex instanceof NoResourceException) {
			LOGGER.warn("系统发生业务异常，异常原因：访问的资源不存在", ex);
		} else if (ex instanceof NotLoginException) {
			// FIXME 如果没有登录，再次登录后需要重新定位到该操作页面
			LOGGER.warn("系统发生业务异常，异常原因：没有登录", ex);
			String requestFrom = null;
			String curpage = request.getParameter("curpage");
			if (curpage == null) {
				requestFrom = request.getRequestURL().toString();
			} else {
				requestFrom = request.getRequestURL().append("?curpage=").append(curpage)
						.toString();
			}
			try {
				requestFrom = URLEncoder.encode(requestFrom, "UTF-8");
			} catch (UnsupportedEncodingException e) {
				LOGGER.warn("系统不支持UTF-8编码", e);
			}
			return "redirect:/login" + URL_SUFFIX + "?requestFrom=" + requestFrom;
		} else if (ex instanceof NoOperatePermissionException) {
			// 如果没有操作权限而且没有登录，则需要重新登录，而且登录后直接进入首页
			// 对于删除类操作即使没有登录，重新登录后也不能继续做删除操作
			LOGGER.warn("系统发生业务异常，异常原因：没有操作权限", ex);
			User user = (User) WebHelper.getSessionAttribute(request, Constant.SESSION_USER);
			if (user == null) {
				return "redirect:/login" + URL_SUFFIX;
			}
		} else if (ex instanceof OperateFailedException) {
			LOGGER.warn("系统发生业务异常，异常原因：操作失败", ex);
		} else {
			LOGGER.warn("系统发生业务异常，异常原因：", ex);
		}
		return null;
	}

	@ExceptionHandler(Exception.class)
	protected String handlerException(HttpServletRequest request, Exception e) {
		if (e instanceof BindException) {
			LOGGER.error("Spring绑定参数错误，可能地址中的参数不合法：", e);
		} else {
			LOGGER.error("系统发生未知异常，异常原因：", e);
		}
		return "error";
	}

	/**
	 * 表单校验方法 表单校验必须调用此方法
	 * 
	 * @param formName
	 *            validation-xxx.xml中配置的form的name
	 * @param bean
	 *            需要验证的Bean或者Map或者String
	 * @return 如果不空表示校验不通过，在调用后必须调用{@link BaseController#processValidationErrors(String, String, ModelAndView)}
	 * 
	 * */
	protected <T> String validateForm(String formName, T bean) {
		Errors errors = ValidationUtils.validateForm(formName, bean);
		String[] errorMsgs = ValidationUtils.getAllErrorMessages(errors);
		if (errorMsgs.length < 1) {
			return null;
		} else {
			return errorMsgs[0];
		}
	}
	
	/**
	 * 表单验证失败的处理
	 * @param msgAttr 错误信息设置到returnMav的model中
	 * @param errMsg 错误信息
	 * @param 错误需要返回的ModelAndView
	 * @return 返回的设置后的returnMav
	 * */
	protected ModelAndView  processValidationErrors(String msgAttr, String errMsg, ModelAndView returnMav) {
		if(errMsg != null) {
			returnMav.addObject(msgAttr, errMsg);
		}
		return returnMav;
	}
}
